package com.kerwin.getandsetredis;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.kerwin.annotations.RedisGetAndSet;
import com.kerwin.entity.returnjson.E;
import com.kerwin.exception.HandlerException;
import com.kerwin.rolemgt.entity.Department;
import com.kerwin.utils.JackSonUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Component
@Aspect
public class GetAndSetRedisAspect {
    @Resource
    RedisTemplate<String, Object> redisTemplate;
    private ObjectMapper objectMapper = JackSonUtil.objectMapper;
    private static Logger log = LoggerFactory.getLogger(GetAndSetRedisAspect.class);

    /*这里写的是注解，我去找切面类去了*/
    @Pointcut("@annotation(com.kerwin.annotations.RedisGetAndSet)")
    public void redis(){}

    @Around("redis()")
    public Object getSetRedis(ProceedingJoinPoint jp){

        /*获取注解上的几个值*/
        Signature signature = jp.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        RedisGetAndSet annotation = method.getAnnotation(RedisGetAndSet.class);
        String keyName = annotation.keyName();
        Class<?> clz = annotation.clz();
        String frontLog = annotation.frontLog();
        String behind = annotation.behind();

        /*从redis里面看看有没有值*/
        ValueOperations<String, Object> stringOpera = redisTemplate.opsForValue();
        Object o = stringOpera.get(keyName);
        if(Objects.nonNull(o) && o instanceof String){
            String s = String.valueOf(o);
            /*在这里指定一下 反序列化的实体类*/
            try {
                List<Department> departments = objectMapper.readValue(s, objectMapper.getTypeFactory().constructParametricType(List.class, clz));
                log.info(frontLog);
                return departments;

            } catch (JsonProcessingException e) {
                throw new HandlerException(E.JSON_ERROR);
            }

        }

        /*代理类方法*/
        Object proceed=null;
        try {
            proceed = jp.proceed();
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }

        /*往redis里面存*/
        ObjectMapper objectMapper = JackSonUtil.objectMapper;
        String departJson=null;
        try {
            /*这里可能出错，我可能需要强制*/
            departJson = objectMapper.writeValueAsString(proceed);
        } catch (JsonProcessingException e) {
            throw new HandlerException(E.JSON_ERROR);
        }

        stringOpera.set(keyName, departJson, 30, TimeUnit.MINUTES);
        log.info(behind);

        return proceed;
    }


}
